package com.ruoyi.cm.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.ruoyi.base.domain.BaseBsZd;
import com.ruoyi.base.mapper.BaseBsZdMapper;
import com.ruoyi.cm.domain.CmBsQs;
import com.ruoyi.cm.domain.bo.CmBdQsCountBo;
import com.ruoyi.cm.mapper.CmBsQsMapper;
import com.ruoyi.cm.service.ICmBdQsCountService;
import com.ruoyi.common.utils.BigDecimalUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.system.domain.SysOss;
import com.ruoyi.system.mapper.SysOssMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import com.ruoyi.cm.domain.bo.CmBaSettleDeductDetailBo;
import com.ruoyi.cm.domain.vo.CmBaSettleDeductDetailVo;
import com.ruoyi.cm.domain.CmBaSettleDeductDetail;
import com.ruoyi.cm.mapper.CmBaSettleDeductDetailMapper;
import com.ruoyi.cm.service.ICmBaSettleDeductDetailService;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 其他计量详情Service业务层处理
 *
 * @author zyb
 * @date 2024-09-24
 */
@RequiredArgsConstructor
@Service
public class CmBaSettleDeductDetailServiceImpl implements ICmBaSettleDeductDetailService {

    private final CmBaSettleDeductDetailMapper baseMapper;
    private final CmBsQsMapper qsMapper;
    private final BaseBsZdMapper zdMapper;
    private final SysOssMapper ossMapper;
    private final ICmBdQsCountService bdQsCountService;

    /**
     * 查询其他计量详情
     */
    @Override
    public CmBaSettleDeductDetailVo queryById(Long deductDetailId){
        return baseMapper.selectVoById(deductDetailId);
    }

    /**
     * 查询其他计量详情列表
     */
    @Override
    public TableDataInfo<CmBaSettleDeductDetailVo> queryPageList(CmBaSettleDeductDetailBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<CmBaSettleDeductDetail> lqw = buildQueryWrapper(bo);
        Page<CmBaSettleDeductDetailVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        List<CmBaSettleDeductDetailVo> records = result.getRecords();
        if(CollUtil.isNotEmpty(records)) {
            records.stream().forEach(e -> {
                String fileNo = e.getFileNo();
                if (StringUtils.isNotBlank(fileNo)) {
                    String[] split = fileNo.split(",");
                    List<String> fileNos = new ArrayList<>(split.length);
                    Collections.addAll(fileNos, split);
                    List<Long> ossIds = new ArrayList<>();
                    fileNos.stream().forEach(item -> ossIds.add(Long.valueOf(item)));
                    LambdaQueryWrapper<SysOss> wrapper = new LambdaQueryWrapper();
                    wrapper.in(SysOss::getOssId, ossIds);
                    List<SysOss> list = ossMapper.selectList(wrapper);
                    e.setFileList(list);
                }
            });
            records.stream().forEach(e -> e.setDeductDetailMoney(BigDecimalUtil.defaultValue(e.getDeductDetailMoney(), 2)));
        }
        return TableDataInfo.build(result);
    }

    /**
     * 查询其他计量详情列表
     */
    @Override
    public List<CmBaSettleDeductDetailVo> queryList(CmBaSettleDeductDetailBo bo) {
        LambdaQueryWrapper<CmBaSettleDeductDetail> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<CmBaSettleDeductDetail> buildQueryWrapper(CmBaSettleDeductDetailBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<CmBaSettleDeductDetail> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getSettleId() != null, CmBaSettleDeductDetail::getSettleId, bo.getSettleId());
        lqw.eq(StringUtils.isNotBlank(bo.getDeductType()), CmBaSettleDeductDetail::getDeductType, bo.getDeductType());
        lqw.eq(bo.getDeductDetailMoney() != null, CmBaSettleDeductDetail::getDeductDetailMoney, bo.getDeductDetailMoney());
        lqw.eq(bo.getDeductTime() != null, CmBaSettleDeductDetail::getDeductTime, bo.getDeductTime());
        lqw.eq(bo.getBdId() != null, CmBaSettleDeductDetail::getBdId, bo.getBdId());
        lqw.eq(bo.getZdId() != null, CmBaSettleDeductDetail::getZdId, bo.getZdId());
        lqw.eq(bo.getQsId() != null, CmBaSettleDeductDetail::getQsId, bo.getQsId());
        return lqw;
    }

    /**
     * 新增其他计量详情
     */
    @Override
    @DSTransactional
    public Boolean insertByBo(CmBaSettleDeductDetailBo bo) {
        CmBaSettleDeductDetail add = BeanUtil.toBean(bo, CmBaSettleDeductDetail.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setDeductDetailId(add.getDeductDetailId());
            //更新标段站点期数计量表；
            CmBdQsCountBo qsCountBo = new CmBdQsCountBo();
            qsCountBo.setBdId(bo.getBdId());
            qsCountBo.setZdId(bo.getZdId());
            qsCountBo.setQsId(bo.getQsId());
            bdQsCountService.update(qsCountBo);
        }
        return flag;
    }

    /**
     * 修改其他计量详情
     */
    @Override
    @DSTransactional
    public Boolean updateByBo(CmBaSettleDeductDetailBo bo) {
        CmBaSettleDeductDetail update = BeanUtil.toBean(bo, CmBaSettleDeductDetail.class);
        validEntityBeforeSave(update);
        //先删除本次修改删掉的附件；
        Set<Long> fileNoOld = bo.getFileNoOld();
        Set<Long> fileNos = bo.getFileNos();
        Set<Long> deleteFiles;
        if(CollUtil.isNotEmpty(fileNoOld)){
            if(CollUtil.isEmpty(fileNos)){
                deleteFiles = fileNoOld;
            } else {
                deleteFiles = fileNoOld.stream().filter(e-> !fileNos.contains(e)).collect(Collectors.toSet());
            }
            if(CollUtil.isNotEmpty(deleteFiles)){
                ossMapper.deleteBatchIds(deleteFiles);
            }
        }
        boolean reslut = baseMapper.updateById(update) > 0;
        //更新标段站点期数计量表；
        CmBdQsCountBo qsCountBo = new CmBdQsCountBo();
        qsCountBo.setBdId(bo.getBdId());
        qsCountBo.setZdId(bo.getZdId());
        qsCountBo.setQsId(bo.getQsId());
        bdQsCountService.update(qsCountBo);
        return reslut;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(CmBaSettleDeductDetail entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除其他计量详情
     */
    @Override
    @DSTransactional
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        Long id = ids.stream().findFirst().get();
        CmBaSettleDeductDetailVo bo = baseMapper.selectVoById(id);
        boolean flag = baseMapper.deleteBatchIds(ids) > 0;
        //更新标段站点期数计量表；
        if(flag){
            CmBdQsCountBo qsCountBo = new CmBdQsCountBo();
            qsCountBo.setBdId(bo.getBdId());
            qsCountBo.setZdId(bo.getZdId());
            qsCountBo.setQsId(bo.getQsId());
            bdQsCountService.update(qsCountBo);
        }
        return flag;
    }

    /**
     * 获取标段下所有站点的其他计量数据；
     * @param bo
     * @return
     */
    @Override
    public List<CmBaSettleDeductDetailVo> bdlist(CmBaSettleDeductDetailBo bo) {
        Long bdId = bo.getBdId();
        List<CmBaSettleDeductDetailVo> returnList = new ArrayList<>();
        List<BaseBsZd> zdList = zdMapper.selectList(new LambdaQueryWrapper<BaseBsZd>().eq(BaseBsZd::getBdId, bdId));
        List<CmBaSettleDeductDetail> deductDetails = baseMapper.selectList(new LambdaQueryWrapper<CmBaSettleDeductDetail>().eq(CmBaSettleDeductDetail::getBdId, bdId));
        Map<Long, List<CmBaSettleDeductDetail>> zdMaps = deductDetails.stream().collect(Collectors.groupingBy(CmBaSettleDeductDetail::getZdId));
        if (CollUtil.isNotEmpty(zdList)) {
            for (BaseBsZd zd : zdList) {
                List<CmBaSettleDeductDetail> details = zdMaps.get(zd.getId());
                if (CollUtil.isNotEmpty(details)) {
                    //查询期数管理；
                    List<CmBsQs> qsList = qsMapper.selectList(new LambdaQueryWrapper<CmBsQs>().eq(CmBsQs::getBdId, bdId).orderByAsc(CmBsQs::getSettleIndex));
                    Map<Long, List<CmBaSettleDeductDetail>> qsIdSettleMap = details.stream().collect(Collectors.groupingBy(CmBaSettleDeductDetail::getQsId));
                    for (CmBsQs qs : qsList) {
                        List<CmBaSettleDeductDetail> deductDetails1 = qsIdSettleMap.get(qs.getQsId());
                        CmBaSettleDeductDetailVo vo = new CmBaSettleDeductDetailVo();
                        vo.setZdId(zd.getId());
                        vo.setZdName(zd.getName());
                        vo.setJfje( new BigDecimal("0.00"));
                        vo.setKhkgyfk(new BigDecimal("0.00"));
                        vo.setDkp(new BigDecimal("0.00"));
                        vo.setQs(qs.getSettleIndex());
                        returnList.add(vo);
                        if (CollUtil.isNotEmpty(deductDetails1)) {
                            List<CmBaSettleDeductDetail> jfjs = deductDetails1.stream().filter(e -> "1".equals(e.getDeductType())).collect(Collectors.toList());
                            List<CmBaSettleDeductDetail> khkgyfk = deductDetails1.stream().filter(e -> "2".equals(e.getDeductType())).collect(Collectors.toList());
                            List<CmBaSettleDeductDetail> dkp = deductDetails1.stream().filter(e -> "3".equals(e.getDeductType())).collect(Collectors.toList());
                            vo.setZdId(zd.getId());
                            vo.setZdName(zd.getName());
                            vo.setJfje(CollUtil.isNotEmpty(jfjs) ? jfjs.get(0).getDeductDetailMoney() : new BigDecimal("0.00"));
                            vo.setKhkgyfk(CollUtil.isNotEmpty(khkgyfk) ? khkgyfk.get(0).getDeductDetailMoney() : new BigDecimal("0.00"));
                            vo.setDkp(CollUtil.isNotEmpty(dkp) ? dkp.get(0).getDeductDetailMoney() : new BigDecimal("0.00"));
                            vo.setQs(qs.getSettleIndex());
                        }
                    }
                }
            }
        }
        return returnList;
    }
}
